﻿using Sunny.UI;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;

namespace SmartMotion.Core
{
    public class GlobalVars
    {
        #region 单例

        private static readonly Lazy<GlobalVars> Instance = new Lazy<GlobalVars>(() => new GlobalVars());

        public static GlobalVars Ins { get; } = Instance.Value;

        private GlobalVars()
        {
            Vars = new ConcurrentDictionary<string, ConcurrentDictionary<string, VarInfo>>();
        }

        #endregion 单例

        #region 属性

        public ConcurrentDictionary<string, ConcurrentDictionary<string, VarInfo>> Vars { get; }

        #endregion 属性

        #region 分组常量

        public static readonly string FlowVars = "FlowVars";
        public static readonly string MotionMgr = "MotionMgr";
        //public static readonly string IOCards = "IOCards";
        //public static readonly string IOConfig = "IOConfig";
        public static readonly string IOMgr = "IOMgr";
        public static readonly string StationsMgr = "StationsMgr";
        //public static readonly string DI = "DI";
        //public static readonly string DO = "DO";
        public static readonly string Points = "Points";
        public static readonly string ProductPars = "ProductPars";
        public static readonly string SystemPars = "SystemPars";
        //视觉相关
        //报表相关

        #endregion 分组常量

        #region 公共方法

        public void LoadDic(string dicName, string filePath, bool iniValue = true)
        {
            var vars = Json.LoadExt<Dictionary<string, VarInfo>>(filePath);//临时字典用于反序列化
            var dicVars = new ConcurrentDictionary<string, VarInfo>();

            try
            {
                if (vars == null) return;
                ConvertInt(vars, iniValue);
                DicToConcurrentDic(vars, dicVars);
            }
            catch (Exception e)
            {
                UIMessageBox.ShowError($"加载变量集{dicName}时发生了异常\r{e.Message}");
            }
            finally
            {
                if (Ins.Vars.ContainsKey(dicName))
                {
                    Ins.Vars[dicName] = dicVars;
                }
                else
                {
                    Ins.Vars.TryAdd(dicName, dicVars);
                }
            }
        }

        public void SaveDic(string dicName, string filePath)
        {
            if (Ins.Vars.ContainsKey(dicName))
            {
                var vars = new Dictionary<string, VarInfo>();
                ConcurrentDicToDic(Ins.Vars[dicName], vars);
                Json.SaveExt<Dictionary<string, VarInfo>>(filePath, vars);
            }
        }

        public void ComboTreeLoadData(UIComboTreeView tv, string varType)
        {
            tv.Nodes.Clear();
            foreach (var dic in Vars.Keys)
            {
                var dicNode = new TreeNode(dic);
                var groups = Vars[dic].Values.Select(varInfo => varInfo.Group).ToList().Distinct().ToList();
                foreach (var @group in groups)
                {
                    var groupNode = new TreeNode(@group);
                    foreach (var varInfo in Vars[dic].Values)
                    {
                        if (varInfo.Group == @group)
                        {
                            if (varInfo.Type == varType)
                            {
                                var node = groupNode.Nodes.Add(varInfo.Name);
                                node.Tag = varInfo.VarId;
                            }
                        }
                    }
                    if (groupNode.Nodes.Count > 0)
                    {
                        dicNode.Nodes.Add(groupNode);
                    }
                }
                if (dicNode.Nodes.Count > 0)
                {
                    tv.Nodes.Add(dicNode);
                }
            }
        }

      
        public void ComboTreeLoadData<T>(UIComboTreeView tv)
        {
            tv.Nodes.Clear();
            foreach (string dic in Vars.Keys)
            {
                TreeNode dicNode = new TreeNode(dic);
                var groups = Vars[dic].Values.Select(varInfo => varInfo.Group).ToList().Distinct().ToList();
                foreach (var group in groups)
                {
                    TreeNode groupNode = new TreeNode(@group);

                    foreach (var varInfo in Vars[dic].Values)
                    {
                        if (!Vars[dic].ContainsKey(varInfo.Name)) continue;
                        if (Vars[dic][varInfo.Name].Group == @group)
                        {
                            if (!string.IsNullOrEmpty(varInfo.Type))
                            {
                                if (varInfo.Value is T)
                                {
                                    var node = groupNode.Nodes.Add(varInfo.Name);
                                    node.Tag = varInfo.VarId;
                                }
                            }
                        }
                    }

                    if (groupNode.Nodes.Count > 0)
                    {
                        dicNode.Nodes.Add(groupNode);
                    }
                }

                if (dicNode.Nodes.Count > 0)
                {
                    tv.Nodes.Add(dicNode);
                }
            }
        }

        public void ComboTreeLoadData(UIComboTreeView tv, List<string> varType)
        {
            tv.Nodes.Clear();
            foreach (string dic in Vars.Keys)
            {
                TreeNode dicNode = new TreeNode(dic);
                var groups = Vars[dic].Values.Select(varInfo => varInfo.Group).ToList().Distinct().ToList();
                foreach (var group in groups)
                {
                    TreeNode groupNode = new TreeNode(@group);

                    foreach (var varInfo in Vars[dic].Values)
                    {
                        if (!Vars[dic].ContainsKey(varInfo.Name)) break;
                        if (Vars[dic][varInfo.Name].Group == @group)
                        {
                            if (!string.IsNullOrEmpty(varInfo.Type))
                            {
                                if (varType.Contains(varInfo.Type))
                                {
                                    var node = groupNode.Nodes.Add(varInfo.Name);
                                    node.Tag = varInfo.VarId;
                                }
                            }
                        }
                    }

                    if (groupNode.Nodes.Count > 0)
                    {
                        dicNode.Nodes.Add(groupNode);
                    }
                }

                if (dicNode.Nodes.Count > 0)
                {
                    tv.Nodes.Add(dicNode);
                }
            }
        }


        public VarInfo GetVar(string varID)
        {
            //var varInfl = new VarInfo();
            //foreach (var dic in Vars)
            //{
            //    foreach (var varInfo in dic.Value)
            //    {
            //        if (varInfo.Value.VarId == varID)
            //        {
            //            varInfl = dic.Value[varInfo.Key];
            //        }
            //    }
            //}

            return (from dic in Vars //from==foreach
                    from varInfo in dic.Value //from==foreach
                    where varInfo.Value.VarId == varID           //where==if
                    select varInfo.Value).FirstOrDefault();  //select==return
        }
        /// <summary>
        /// 获取所有已使用的类型
        /// </summary>
        /// <returns></returns>
        public List<string> GetAllTypes()
        {
            var typeList = new List<string>();
            foreach (var dicVar in Vars)
            {
                foreach (var varInfo in dicVar.Value)
                {
                    if (!typeList.Contains(varInfo.Value.Type))
                    {
                        typeList.Add(varInfo.Value.Type);
                    }
                }
            }
            return typeList;
        }

        public string GetConfigPath(string folder = "")
        {

            string allConfigPath = Environment.CurrentDirectory + "\\Config\\";
            if (!Directory.Exists(allConfigPath))
            {
                Directory.CreateDirectory(allConfigPath);
            }
            string cfgPath = allConfigPath;
            if (!string.IsNullOrEmpty(folder))
            {
                cfgPath += "\\" + folder;
            }

            if (!Directory.Exists(cfgPath))
            {
                Directory.CreateDirectory(cfgPath);
            }
            return cfgPath;
        }

        #endregion 公共方法

        #region 私有方法

        //普通字典转换并发字典
        private static void DicToConcurrentDic(Dictionary<string, VarInfo> dic,
            ConcurrentDictionary<string, VarInfo> conDic)
        {
            conDic.Clear();
            foreach (var varInfo in dic)
            {
                conDic.TryAdd(varInfo.Key, varInfo.Value);
            }
        }

        //并发字典转普通字典
        private static void ConcurrentDicToDic(ConcurrentDictionary<string, VarInfo> conDic,
            Dictionary<string, VarInfo> dic)
        {
            dic.Clear();
            foreach (var varInfo in conDic)
            {
                dic.Add(varInfo.Key, varInfo.Value);
            }
        }

        /// <summary>
        /// 解决动态类型int会全部转换为int64的问题
        /// </summary>
        /// <param name="var"></param>
        /// <param name="iniValue"></param>
        private static void ConvertInt(Dictionary<string, VarInfo> var, bool iniValue = true)
        {
            foreach (var par in var.Values)
            {
                Type type = Type.GetType(par.Type);
                ConvertToInt(type, par, iniValue);
                if (iniValue)
                {
                    par.Value = par.InitValue;
                }
            }
        }

        private static void ConvertToInt(Type type, VarInfo par, bool iniValue = true)
        {
            if (type == typeof(int))
            {
                par.Value = Convert.ToInt32(iniValue ? par.InitValue : par.Value);
            }

            if (type == typeof(int))
            {
                par.InitValue = Convert.ToInt32(iniValue ? par.InitValue : par.Value);
            }
            else if (type == typeof(uint))
            {
                par.InitValue = Convert.ToUInt32(iniValue ? par.InitValue : par.Value);
            }
            else if (type == typeof(short))
            {
                par.InitValue = Convert.ToInt16(iniValue ? par.InitValue : par.Value);
            }
            else if (type == typeof(ushort))
            {
                par.InitValue = Convert.ToUInt16(iniValue ? par.InitValue : par.Value);
            }
            else if (type == typeof(int[]))
            {
                par.InitValue = (int[])(iniValue ? par.InitValue : par.Value);
            }
            else if (type == typeof(uint[]))
            {
                par.InitValue = (int[])(iniValue ? par.InitValue : par.Value);
            }
            else if (type == typeof(short[]))
            {
                par.InitValue = (int[])(iniValue ? par.InitValue : par.Value);
            }
            else if (type == typeof(ushort[]))
            {
                par.InitValue = (int[])(iniValue ? par.InitValue : par.Value);
            }
        }

        #endregion 私有方法
    }
}